using System;
using System.Collections.Generic;
using System.Linq;
using Nop.Core.Data;
using Nop.Core.Domain.Topics;
using Nop.Services.Events;
using Nop.Core.Caching;

namespace Nop.Services.Topics
{
    /// <summary>
    /// Topic service
    /// </summary>
    public partial class TopicService : ITopicService
    {
        #region Fields

        private readonly IRepository<Topic> _topicRepository;
        private readonly IEventPublisher _eventPublisher;
		private readonly ICacheManager _cacheManager;

		private const string topicCacheKey = "nop_topic_by_{0}";
		private readonly int CACHE_MINUTES = 20;
        #endregion

        #region Ctor

		public TopicService(IRepository<Topic> topicRepository, IEventPublisher eventPublisher, ICacheManager cacheManager)
        {
            _topicRepository = topicRepository;
            _eventPublisher = eventPublisher;
			_cacheManager = cacheManager;
        }

        #endregion

        #region Methods

        /// <summary>
        /// Deletes a topic
        /// </summary>
        /// <param name="topic">Topic</param>
        public virtual void DeleteTopic(Topic topic)
        {
            if (topic == null)
                throw new ArgumentNullException("topic");

            _topicRepository.Delete(topic);

			_cacheManager.Remove(string.Format(topicCacheKey, topic.Id));
			_cacheManager.Remove(string.Format(topicCacheKey, topic.SystemName));
			_cacheManager.Remove(string.Format(topicCacheKey, "all"));
            //event notification
            _eventPublisher.EntityDeleted(topic);
        }

        /// <summary>
        /// Gets a topic
        /// </summary>
        /// <param name="topicId">The topic identifier</param>
        /// <returns>Topic</returns>
        public virtual Topic GetTopicById(int topicId)
        {
			var result = _cacheManager.Get(string.Format(topicCacheKey, topicId), CACHE_MINUTES, () =>
			{
				if (topicId == 0)
					return null;

				return _topicRepository.GetById(topicId);
			});
			return result;
        }

        /// <summary>
        /// Gets a topic
        /// </summary>
        /// <param name="systemName">The topic system name</param>
        /// <returns>Topic</returns>
        public virtual Topic GetTopicBySystemName(string systemName)
        {
			var result = _cacheManager.Get(string.Format(topicCacheKey, systemName), CACHE_MINUTES, () =>
			{
				if (String.IsNullOrEmpty(systemName))
					return null;

				var query = from t in _topicRepository.Table
							where t.SystemName == systemName
							select t;

				return query.FirstOrDefault();
			});
			return result;            
        }

        /// <summary>
        /// Gets all topics
        /// </summary>
        /// <returns>Topics</returns>
		public virtual IList<Topic> GetAllTopics(string prefix = null)
        {
			var result = _cacheManager.Get(string.Format(topicCacheKey, "all"), CACHE_MINUTES, () =>
			{				
				var query = from t in _topicRepository.Table
							select t;

				if (!string.IsNullOrEmpty(prefix))
					query = query.Where(t => t.SystemName.StartsWith(prefix, StringComparison.OrdinalIgnoreCase));
				query = query.OrderBy(t => t.SystemName);
				var topics = query.ToList();
				return topics;
			});
			return result;
        }

        /// <summary>
        /// Inserts a topic
        /// </summary>
        /// <param name="topic">Topic</param>
        public virtual void InsertTopic(Topic topic)
        {
            if (topic == null)
                throw new ArgumentNullException("topic");

            _topicRepository.Insert(topic);
			_cacheManager.Remove(string.Format(topicCacheKey, "all"));
            //event notification
            _eventPublisher.EntityInserted(topic);
        }

        /// <summary>
        /// Updates the topic
        /// </summary>
        /// <param name="topic">Topic</param>
        public virtual void UpdateTopic(Topic topic)
        {
            if (topic == null)
                throw new ArgumentNullException("topic");

            _topicRepository.Update(topic);
			_cacheManager.Remove(string.Format(topicCacheKey, topic.Id));
			_cacheManager.Remove(string.Format(topicCacheKey, topic.SystemName));
			_cacheManager.Remove(string.Format(topicCacheKey, "all"));
            //event notification
            _eventPublisher.EntityUpdated(topic);
        }

        #endregion
    }
}
